﻿using AutoMapper;
using FakeXiecheng.API.Database;
using FakeXiecheng.API.Dto;
using FakeXiecheng.API.Dtos;
using FakeXiecheng.API.Models;
using FakeXiecheng.API.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Serialization;
using System.Reflection;
using System.Text;

namespace FakeXiecheng.API
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.
            builder.Services.AddRazorPages();
            // 配置控制器支持 XML 格式输入/输出（基于 DataContractSerializer）
            builder.Services.AddControllersWithViews(setAction =>
            {
                // 启用对 HTTP Accept Header 的尊重（若客户端不接受 JSON，则返回 406 Not Acceptable）
                setAction.ReturnHttpNotAcceptable = true;
            })
            .AddXmlDataContractSerializerFormatters()
            // 添加控制 API Controller 行为的服务
            .ConfigureApiBehaviorOptions(setupAction =>
            {
                setupAction.InvalidModelStateResponseFactory = context =>
                {
                    var problemDetail = new ValidationProblemDetails(context.ModelState)
                    {
                        Type = "验证类型",
                        Title = "数据验证失败",
                        Status = StatusCodes.Status422UnprocessableEntity,
                        Detail = "请看详细说明",
                        Instance = context.HttpContext.Request.Path
                    };
                    problemDetail.Extensions.Add("traceId", context.HttpContext.TraceIdentifier);
                    return new UnprocessableEntityObjectResult(problemDetail)
                    {
                        ContentTypes = { "application/problem+json" }
                    };
                };
            })
            // 添加 JSON Patch 支持（使用 Newtonsoft.Json）
            .AddNewtonsoftJson(setupAction =>
            {
                // 设置 JSON 序列化时使用驼峰命名（camelCase）
                setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });


            // 配置 JWT 认证
            builder.Services.AddAuthentication(options =>
            {
                // 设置默认的认证方案为 JWT Bearer
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                // 配置 Token 验证参数
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    // 验证签发者
                    ValidateIssuer = true,
                    ValidIssuer = builder.Configuration["Authentication:Issuer"],

                    // 验证接收者
                    ValidateAudience = true,
                    ValidAudience = builder.Configuration["Authentication:Audience"],

                    // 验证令牌有效期
                    ValidateLifetime = true,

                    // 验证签名密钥
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(
                        Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"])),

                    // 允许的时钟偏差（解决服务器时间不同步问题）
                    ClockSkew = TimeSpan.Zero
                };
            });

            // 添加授权服务
            builder.Services.AddAuthorization();
            builder.Services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<AppDbContext>();


            builder.Services.AddTransient<ITouristRouteRepository, TouristRouteRepository>();

            // 配置 AutoMapper 映射规则
            builder.Services.AddAutoMapper(cfg =>
            {
                // TouristRoute 实体映射到 TouristRouteDTO
                cfg.CreateMap<TouristRoute, TouristRouteDTO>()
                    .ForMember(
                        dest => dest.Price,
                        opt => opt.MapFrom(src => src.OriginalPrice * (decimal)(src.DiscountPresent ?? 1))
                    )
                    .ForMember(
                        dest => dest.TravelDays,
                        opt => opt.MapFrom(src => src.TravelDays)
                    )
                    .ForMember(
                        dest => dest.TripType,
                        opt => opt.MapFrom(src => src.TripType)
                    )
                    .ForMember(
                        dest => dest.DepartureCity,
                        opt => opt.MapFrom(src => src.DepartureCity)
                    );

                // 创建旅游路线时的 DTO 映射：TouristRouteForCreateDTO → TouristRoute
                cfg.CreateMap<TouristRouteForCreateDTO, TouristRoute>()
                    .ForMember(dest => dest.Id, opt => opt.MapFrom(src => Guid.NewGuid()));

                // 图片相关映射
                cfg.CreateMap<TouristRoutePicture, TouristRoutePictureForCreateDTO>();
                cfg.CreateMap<TouristRoutePictureForCreateDTO, TouristRoutePicture>();
                cfg.CreateMap<TouristRoutePicture, TouristRoutePicturesDTO>();

                // 更新旅游路线时的双向映射
                cfg.CreateMap<TouristRouteForUpdateDTO, TouristRoute>();
                cfg.CreateMap<TouristRoute, TouristRouteForUpdateDTO>();
            });


            // 从配置文件中读取数据库连接字符串，并注册 AppDbContext 到 DI 容器
            // 使用 MySQL 作为数据库（指定版本为 8.0.44）
            builder.Services.AddDbContext<AppDbContext>(options =>
                options.UseMySql(
                    builder.Configuration.GetConnectionString("DefaultConnection"),
                    new MySqlServerVersion(new Version(8, 0, 44))
                )
            );


            var app = builder.Build();
            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();
            app.MapRazorPages();

            app.MapControllerRoute(
                name: "default",
                pattern: "{controller}/{action=Index}/{id?}");

            app.Run();
        }
    }
}
